package com.sky.service.impl;

import cn.hutool.json.JSONUtil;
import com.sky.dto.GoodsSalesDTO;
import com.sky.dto.ReportDto;
import com.sky.entity.Orders;
import com.sky.entity.User;
import com.sky.mapper.OrdersMapper;
import com.sky.service.OrdersService;
import com.sky.service.ReportService;
import com.sky.service.UserService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * TODO
 *
 * @Author Yjr
 * @Date 2025/6/2 21:09
 */
@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private OrdersService ordersService;
    @Autowired
    private WorkspaceService workspaceService;
    @Autowired
    private UserService userService;
    @Autowired
    private OrdersMapper ordersMapper;

    /**
     * 营业额数据统计
     *
     * @return
     */
    @Override
    public TurnoverReportVO turnoverStatistics(ReportDto dto) {
        LocalDateTime beginTime = null;
        LocalDateTime finishTime = null;
        if (dto.getBegin()!=null && dto.getEnd()!=null) {
            beginTime = LocalDateTime.of(dto.getBegin(), LocalTime.MIN);
            finishTime = LocalDateTime.of(dto.getEnd(), LocalTime.MAX);
        }

        List<Orders> ordersList = ordersService.lambdaQuery()
                .eq(Orders::getStatus, Orders.COMPLETED)
                .between(beginTime!=null&&finishTime!=null,Orders::getOrderTime, beginTime, finishTime)
                .orderByAsc(Orders::getOrderTime)
                .list();

        List<LocalDate> localDates = ordersList.stream()
                .map(x -> x.getOrderTime().toLocalDate()).distinct()
                .collect(Collectors.toList());

        List<BigDecimal> bigDecimalList = localDates.stream().map(x -> {
            LocalDateTime startTime = LocalDateTime.of(x, LocalTime.of(00, 00));
            LocalDateTime endTime = LocalDateTime.of(x, LocalTime.of(23, 59));

            List<Orders> orders = ordersService.lambdaQuery()
                    .eq(Orders::getStatus, Orders.COMPLETED)
                    .between(Orders::getOrderTime, startTime, endTime)
                    .list();

            BigDecimal sum = orders.stream().map(Orders::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            return sum;
        }).collect(Collectors.toList());

        List<String> stringSet = localDates.stream().map(x -> x.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).collect(Collectors.toList());
        String dateList = getStrList(stringSet);
        String turnoverList = getStrList(bigDecimalList);
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        turnoverReportVO.setDateList(dateList);
        turnoverReportVO.setTurnoverList(turnoverList);

        return turnoverReportVO;
    }

    private static String getStrList(Object stringSet) {
        return JSONUtil.toJsonStr(stringSet).substring(1, JSONUtil.toJsonStr(stringSet).length() - 1);
    }

    /**
     * 用户数据统计
     *
     * @param dto
     * @return
     */
    @Override
    public UserReportVO userStatistics(ReportDto dto) {
        LocalDateTime beginTime = null;
        LocalDateTime finishTime = null;
        if (dto.getBegin()!=null && dto.getEnd()!=null) {
            beginTime = LocalDateTime.of(dto.getBegin(), LocalTime.of(00, 00));
            finishTime = LocalDateTime.of(dto.getEnd(), LocalTime.of(23, 59));
        }

        List<User> userList = userService.lambdaQuery()
                .between(beginTime != null && finishTime != null, User::getCreateTime, beginTime, finishTime)
                .orderByAsc(User::getCreateTime)
                .list();

        List<LocalDate> localDates = userList.stream()
                .map(x -> x.getCreateTime().toLocalDate()).distinct()
                .collect(Collectors.toList());

        List<Integer> newUserNumList = new ArrayList<>();
        List<Integer> totalUserNumList = new ArrayList<>();
         localDates.forEach(x -> {
             List<User> newUserList = userList.stream().filter(j -> j.getCreateTime().toLocalDate().equals(x)).collect(Collectors.toList());
             newUserNumList.add(newUserList.size());
             
             List<User> totalUserList = userList.stream().filter(j -> j.getCreateTime().toLocalDate().equals(x)||j.getCreateTime().toLocalDate().isBefore(x)).collect(Collectors.toList());
             totalUserNumList.add(totalUserList.size());
         });

        UserReportVO reportVO = new UserReportVO();
        List<String> stringSet = localDates.stream().map(x -> x.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).collect(Collectors.toList());
        reportVO.setDateList(getStrList(stringSet));
        reportVO.setNewUserList(getStrList(newUserNumList));
        reportVO.setTotalUserList(getStrList(totalUserNumList));
         
        return reportVO;
    }

    /**
     * 订单统计
     *
     * @param dto
     * @return
     */
    @Override
    public OrderReportVO ordersStatistics(ReportDto dto) {
        LocalDateTime beginTime = null;
        LocalDateTime finishTime = null;
        if (dto.getBegin()!=null && dto.getEnd()!=null) {
            beginTime = LocalDateTime.of(dto.getBegin(), LocalTime.of(00, 00));
            finishTime = LocalDateTime.of(dto.getEnd(), LocalTime.of(23, 59));
        }

        List<Orders> ordersList = ordersService.lambdaQuery()
                .between(beginTime!=null&&finishTime!=null,Orders::getOrderTime, beginTime, finishTime)
                .orderByAsc(Orders::getOrderTime)
                .list();

        List<LocalDate> localDates = ordersList.stream()
                .map(x -> x.getOrderTime().toLocalDate()).distinct()
                .collect(Collectors.toList());

        List<Integer> orderCountList = new ArrayList<>();
        List<Integer> validOrderCountList = new ArrayList<>();
        localDates.forEach(x->{
            int orderNum = ordersList.stream().filter(j -> j.getOrderTime().toLocalDate().equals(x)).collect(Collectors.toList()).size();
            orderCountList.add(orderNum);
            int validOrderNum = ordersList.stream().filter(j -> j.getOrderTime().toLocalDate().equals(x)&&!(j.getStatus().equals(6)||j.getStatus().equals(7))).collect(Collectors.toList()).size();
            validOrderCountList.add(validOrderNum);
        });

        Double orderCompletionRate= (double)ordersList.stream().filter(j -> !(j.getStatus().equals(6)||j.getStatus().equals(7))).collect(Collectors.toList()).size() /ordersList.size();

        OrderReportVO reportVO = new OrderReportVO();
        List<String> stringSet = localDates.stream().map(x -> x.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).collect(Collectors.toList());
        reportVO.setDateList(getStrList(stringSet));
        reportVO.setOrderCountList(getStrList(orderCountList));
        reportVO.setValidOrderCountList(getStrList(validOrderCountList));
        reportVO.setTotalOrderCount(ordersList.size());
        reportVO.setValidOrderCount(ordersList.stream().filter(j -> !(j.getStatus().equals(6)||j.getStatus().equals(7))).collect(Collectors.toList()).size());
        reportVO.setOrderCompletionRate(orderCompletionRate);
        return reportVO;
    }

    /**
     * 销量排名统计
     *
     * @param dto
     * @return
     */
    @Override
    public SalesTop10ReportVO top10(ReportDto dto) {
        LocalDateTime begin = LocalDateTime.of(dto.getBegin(), LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(dto.getEnd(), LocalTime.MAX);
        List<GoodsSalesDTO> goodsSalesDTOList = ordersMapper.getSalesTop10(begin, end);
        List<String> nameList = goodsSalesDTOList.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
        List<Integer> numberList = goodsSalesDTOList.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());


        SalesTop10ReportVO reportVO = new SalesTop10ReportVO();
        reportVO.setNameList(getStrList(StringUtils.join(nameList)));
        reportVO.setNumberList(getStrList(StringUtils.join(numberList)));
        return reportVO;
    }

    /**
     * 导出运营数据报表
     *
     * @param response
     */
    @Override
    public void exportBusinessData(HttpServletResponse response) throws IOException {
        //获取时间范围
        LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        LocalDateTime beginTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).minusDays(30);

        //获取营业数据
        BusinessDataVO businessDataVO = workspaceService.getBusinessData(beginTime, endTime);


            // 获取模板路径（模板放在resources/templates目录下）
        ClassPathResource templateResource = new ClassPathResource("templates/运营数据报表模板.xlsx");
        InputStream resourceInputStream = templateResource.getInputStream();

        //基于提供好的模板创建excel表格对象
        XSSFWorkbook excel = new XSSFWorkbook(resourceInputStream);

        //获得Excel文件中的一个Sheet页
        XSSFSheet sheet = excel.getSheet("sheet1");

        sheet.getRow(1).getCell(1).setCellValue(beginTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))+"至"+endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        //获取到第4行
        XSSFRow row = sheet.getRow(3);

        //获取单元格
        row.getCell(2).setCellValue(businessDataVO.getTurnover());
        row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
        row.getCell(6).setCellValue(businessDataVO.getNewUsers());
        row = sheet.getRow(4);
        row.getCell(2).setCellValue(businessDataVO.getValidOrderCount());
        row.getCell(4).setCellValue(businessDataVO.getUnitPrice());

        //获取明细数据
        for (int i = 0; i < 30; i++) {
            LocalDateTime stareTime=beginTime.plusDays(i);
            LocalDateTime overTime = beginTime.plusDays(1 + i);
            BusinessDataVO businessData = workspaceService.getBusinessData(stareTime, overTime);

            row = sheet.getRow(7+i);
            row.getCell(1).setCellValue(stareTime.toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            row.getCell(2).setCellValue(businessData.getTurnover());
            row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row.getCell(6).setCellValue(businessData.getNewUsers());
            row.getCell(3).setCellValue(businessData.getValidOrderCount());
            row.getCell(5).setCellValue(businessData.getUnitPrice());
        }

        ServletOutputStream outputStream = response.getOutputStream();
        excel.write(outputStream);
        outputStream.close();
        excel.close();
    }
}
